home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sun Solutions 1997 April to September
/
Sun Solutions CD - APR '97 - SEP '97 (704-3778-12 Rev. H)(Sun Microsystems, Inc.)(1997).iso
/
products
/
bin
/
httpd
/
src
/
http_access.c
next >
Wrap
C/C++ Source or Header
|
1995-05-18
|
9KB
|
297 lines
/*
* http_access: Security options etc.
*
* All code contained herein is covered by the Copyright as distributed
* in the README file in the main directory of the distribution of
* NCSA HTTPD.
*
* Based on NCSA HTTPd 1.3 by Rob McCool
*
* 03-12-95 blong
* Added patch to fix ALLOW_THEN_DENY
*
*/
#include "httpd.h"
#include "new.h"
int in_domain(char *domain, char *what) {
int dl=strlen(domain);
int wl=strlen(what);
if((wl-dl) >= 0)
return(!strcmp(domain,&what[wl-dl]));
else
return 0;
}
int in_ip(char *domain, char *what) {
return(!strncmp(domain,what,strlen(domain)));
}
int find_allow(int x, int m) {
register int y;
if(sec[x].num_allow[m] < 0)
return 1;
for(y=0;y<sec[x].num_allow[m];y++) {
if(!strcmp("all",sec[x].allow[m][y]))
return 1;
if(remote_host && isalpha(remote_host[0]))
if(in_domain(sec[x].allow[m][y],remote_host))
return 1;
if(in_ip(sec[x].allow[m][y],remote_ip))
return 1;
}
return 0;
}
int find_deny(int x, int m) {
register int y;
if(sec[x].num_deny[m] < 0)
return 1;
for(y=0;y<sec[x].num_deny[m];y++) {
if(!strcmp("all",sec[x].deny[m][y]))
return 1;
if(remote_host && isalpha(remote_host[0]))
if(in_domain(sec[x].deny[m][y],remote_host))
return 1;
if(in_ip(sec[x].deny[m][y],remote_ip))
return 1;
}
return 0;
}
void check_dir_access(int x, int m, int *w, int *n) {
if(sec[x].auth_type)
auth_type = sec[x].auth_type;
if(sec[x].auth_name)
auth_name = sec[x].auth_name;
if(sec[x].auth_pwfile)
auth_pwfile = sec[x].auth_pwfile;
if(sec[x].auth_grpfile)
auth_grpfile = sec[x].auth_grpfile;
if(sec[x].order[m] == ALLOW_THEN_DENY) {
*w=0;
if(find_allow(x,m))
*w=1;
if(find_deny(x,m))
*w=0;
} else if(sec[x].order[m] == DENY_THEN_ALLOW) {
if(find_deny(x,m))
*w=0;
if(find_allow(x,m))
*w=1;
}
else
*w = find_allow(x,m) && (!find_deny(x,m));
if(sec[x].num_auth[m])
*n=x;
}
void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
char *allow_options,FILE *out)
{
int will_allow, need_auth, num_dirs;
char opts[MAX_STRING_LEN], override[MAX_STRING_LEN];
char path[MAX_STRING_LEN], d[MAX_STRING_LEN];
char errstr[MAX_STRING_LEN];
register int x,y,z,n;
if(S_ISDIR(finfo->st_mode)) strcpy_dir(path,p);
else lim_strcpy(path,p, MAX_STRING_LEN);
no2slash(path);
num_dirs = count_dirs(path);
will_allow = 1;
need_auth = -1;
auth_type = NULL;
auth_name = NULL;
auth_pwfile = NULL;
auth_grpfile = NULL;
user[0] = '\0';
groupname[0] = '\0';
reset_mime_vars();
for(x=0;x<num_dirs;x++) {
opts[x] = OPT_ALL;
override[x] = OR_ALL;
}
n=num_dirs-1;
for(x=0;x<num_sec;x++) {
if(is_matchexp(sec[x].d)) {
if(!strcmp_match(path,sec[x].d)) {
for(y=0;y<num_dirs;y++) {
if(!(sec[x].opts & OPT_UNSET))
opts[y] = sec[x].opts;
override[y] = sec[x].override;
}
}
check_dir_access(x,m,&will_allow,&need_auth);
}
else if(!strncmp(path,sec[x].d,strlen(sec[x].d))) {
for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
if(!(sec[x].opts & OPT_UNSET))
opts[y] = sec[x].opts;
override[y] = sec[x].override;
}
check_dir_access(x,m,&will_allow,&need_auth);
}
}
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS)) ||
(opts[n] & OPT_SYM_OWNER))
{
for(x=0;x<num_dirs;x++) {
y = num_sec;
make_dirstr(path,x+1,d);
if((!(opts[x] & OPT_SYM_LINKS)) || (opts[x] & OPT_SYM_OWNER)) {
struct stat lfi,fi;
lstat(d,&lfi);
if(!(S_ISDIR(lfi.st_mode))) {
if(opts[x] & OPT_SYM_OWNER) {
char realpath[512];
int bsz;
if((bsz = readlink(d,realpath,256)) == -1)
goto bong;
realpath[bsz] = '\0';
if(realpath[0] != '/') {
char t[260];
strcpy(t,"../");
strcpy(&t[3],realpath);
make_full_path(d,t,realpath);
getparents(realpath);
}
lstat(realpath,&fi);
if(fi.st_uid != lfi.st_uid)
goto bong;
}
else {
bong:
sprintf(errstr,"httpd: will not follow link %s",d);
log_error(errstr);
*allow=0;
*allow_options = OPT_NONE;
return;
}
}
}
if(override[x]) {
parse_htaccess(d,override[x],out);
if(num_sec != y) {
for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
if(!(sec[y].opts & OPT_UNSET))
opts[z] = sec[y].opts;
override[z] = sec[y].override;
}
check_dir_access(y,m,&will_allow,&need_auth);
}
}
}
}
if((!(S_ISDIR(finfo->st_mode))) &&
((!(opts[n] & OPT_SYM_LINKS)) || (opts[n] & OPT_SYM_OWNER))) {
struct stat fi,lfi;
lstat(path,&fi);
if(!(S_ISREG(fi.st_mode))) {
if(opts[n] & OPT_SYM_OWNER) {
char realpath[512];
int bsz;
if((bsz = readlink(path,realpath,256)) == -1)
goto gong;
realpath[bsz] = '\0';
if(realpath[0] != '/') {
char t[260];
strcpy(t,"../");
strcpy(&t[3],realpath);
make_full_path(path,t,realpath);
getparents(realpath);
}
lstat(realpath,&lfi);
if(fi.st_uid != lfi.st_uid)
goto gong;
}
else {
gong:
sprintf(errstr,"httpd: will not follow link %s",path);
log_error(errstr);
*allow=0;
*allow_options = OPT_NONE;
return;
}
}
}
*allow = will_allow;
if(will_allow) {
*allow_options = opts[num_dirs-1];
if(need_auth >= 0)
check_auth(&sec[need_auth],m,out);
}
else *allow_options = 0;
}
void kill_security() {
register int x,y,m;
for(x=0;x<num_sec;x++) {
free(sec[x].d);
for(m=0;m<METHODS;m++) {
for(y=0;y<sec[x].num_allow[m];y++)
free(sec[x].allow[m][y]);
for(y=0;y<sec[x].num_deny[m];y++)
free(sec[x].deny[m][y]);
for(y=0;y<sec[x].num_auth[m];y++)
free(sec[x].auth[m][y]);
}
if(sec[x].auth_type)
free(sec[x].auth_type);
if(sec[x].auth_name)
free(sec[x].auth_name);
if(sec[x].auth_pwfile)
free(sec[x].auth_pwfile);
if(sec[x].auth_grpfile)
free(sec[x].auth_grpfile);
}
}
/* This function should reset the security data structure to contain only
the information given in the access configuration file. It should be
called after any transactions */
void reset_security() {
register int x,y,m;
for(x=num_sec_config;x<num_sec;x++) {
free(sec[x].d);
for(m=0;m<METHODS;m++) {
for(y=0;y<sec[x].num_allow[m];y++)
free(sec[x].allow[m][y]);
for(y=0;y<sec[x].num_deny[m];y++)
free(sec[x].deny[m][y]);
for(y=0;y<sec[x].num_auth[m];y++)
free(sec[x].auth[m][y]);
}
if(sec[x].auth_type)
free(sec[x].auth_type);
if(sec[x].auth_name)
free(sec[x].auth_name);
if(sec[x].auth_pwfile)
free(sec[x].auth_pwfile);
if(sec[x].auth_grpfile)
free(sec[x].auth_grpfile);
}
num_sec = num_sec_config;
}